package com.just.springbootmessage.rabbitmq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * 交换机有四种类型：Direct, topic, Headers and Fanout
 *
 * Direct：direct 类型的行为是”先匹配, 再投送”. 即在绑定时设定一个 routing_key, 消息的routing_key 匹配时, 才会被交换器投送到绑定的队列中去.
 * Topic：按规则转发消息（最灵活）
 * Headers：设置header attribute参数类型的交换机
 * Fanout：转发消息到所有绑定队列
 *
 * Direct Exchange是RabbitMQ默认的交换机模式，也是最简单的模式，根据key全文匹配去寻找队列。
 *
 * Topic Exchange 转发消息主要是根据通配符。 在这种交换机下，队列和交换机的绑定会定义一种路由模式，那么，
 * 通配符就要在这种路由模式和路由键之间匹配后交换机才能转发消息。
 *
 * 在这种交换机模式下：
 *
 * 路由键必须是一串字符，用句号（.） 隔开，比如说 agreements.us，或者 agreements.eu.stockholm 等。
 * 路由模式必须包含一个 星号（*），主要用于匹配路由键指定位置的一个单词，比如说，一个路由模式是这样子：agreements..b.*，
 * 那么就只能匹配路由键是这样子的：第一个单词是 agreements，第四个单词是 b。
 * 井号（#）就表示相当于一个或者多个单词，例如一个匹配模式是agreements.eu.berlin.#，那么，以agreements.eu.berlin开头的路由键都是可以的。
 */
@Configuration
public class RabbitConfig {
    private static final Logger logger=LoggerFactory.getLogger(RabbitConfig.class);
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 开启rabbitmq事务
     */
    @PostConstruct
    public void init(){
        if(this.rabbitTemplate==null){
            logger.warn("rabbitTemplate is null!Please check...");
        }else {
            rabbitTemplate.setChannelTransacted(true);
        }
    }
    @Bean
    public Queue rabbitQueue1(){
        return new Queue(RabbitContent.RABBIT_QUEUE1);
    }
    @Bean
    public Queue rabbitQueue2(){
        return new Queue(RabbitContent.RABBIT_QUEUE2);
    }

    //下面两个队列来测试topic
    @Bean
    public Queue queueMessage(){
        return new Queue(RabbitContent.TOPIC_QUEUE_MESSAGE);
    }
    @Bean
    public Queue queueMessages(){
        return new Queue(RabbitContent.TOPIC_QUEUE_MESSAGES);
    }
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(RabbitContent.TOPIC_EXCHANGE);
    }
    @Bean
    public Binding bindingExchangeMessage(Queue queueMessage,TopicExchange exchange){
        return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
    }

    /**
     * 可以匹配topic开头的队列
     */
    @Bean
    public Binding bindingExchangeMessages(Queue queueMessages,TopicExchange exchange){
        return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
    }

   /* @Bean
    public AmqpTemplate ackAmqpTemplate(){
        Logger logger=LoggerFactory.getLogger(RabbitTemplate.class);
        //使用jackson消息转换器
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
        rabbitTemplate.setEncoding("UTF-8");
        //开启returnCallback
        rabbitTemplate.setReturnCallback((message,replyCode,replyText,exchange,routingKey)->{
                    String correlationId=message.getMessageProperties().getCorrelationIdString();
                    logger.info("消息：{}发送失败，应答码：{}，原因：{}，交换机：{}，路由键{}",correlationId,replyCode,replyText,exchange,routingKey);
                }
        );
        rabbitTemplate.setConfirmCallback((correlationData,ack,cause)->{
            if(ack){
                logger.info("消息发送到exchange成功，id:{}",correlationData.getId());
            }else{
                logger.info("消息发送到exchange失败，原因：{}",cause);
            }
        });
        return rabbitTemplate;
    }
*/
    @Bean
    public Queue rabbitQueueAck(){
        return new Queue("queue.ack");
    }
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange("direct_exchange");
    }
    @Bean
    public Binding bindingDirectExchange(Queue rabbitQueueAck,DirectExchange directExchange ){
        return BindingBuilder.bind(rabbitQueueAck).to(directExchange).with("queue.ack");
    }

}
